package com.huawei.M01.iterator;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

/**
 * 利用前序遍历和中序遍历构造树
 *
 * @author zhiwu
 */
public class ConstructTreePreIn {

    class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        public TreeNode() {
        }

        public TreeNode(int val) {
            this.val = val;
        }

        public TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    public TreeNode buildTree(int[] preorder, int[] inorder) {
        if (preorder == null || preorder.length == 0) {
            return null;
        }
        // 构造新的根节点
        TreeNode root = new TreeNode(preorder[0]);
        Deque<TreeNode> deque = new ArrayDeque<>(preorder.length);
        deque.push(root);
        int inorderIndex = 0;
        for (int i = 1; i < preorder.length; i++) {
            TreeNode node = deque.peek();
            if (node.val != inorder[inorderIndex]) {
                node.left = new TreeNode(preorder[i]);
                deque.push(node.left);
            } else {
                while (!deque.isEmpty() && deque.peek().val == inorder[inorderIndex]) {
                    node = deque.pop();
                    inorderIndex++;
                }
                node.right = new TreeNode(preorder[i]);
                deque.push(node.right);
            }
        }
        return root;
    }

    public List<TreeNode> generateTrees(int n) {
        // 处理边界条件
        if (n == 0) {
            return new ArrayList<>();
        }
        return getTreeNodes(1, n);
    }

    private List<TreeNode> getTreeNodes(int start, int end) {

        List<TreeNode> result = new ArrayList<>();

        if (start > end) {
            result.add(null);
            return result;
        }

        // 循环构造树
        for (int i = start; i <= end; i++) {
            List<TreeNode> leftTree = getTreeNodes(start, i - 1);
            List<TreeNode> rightTree = getTreeNodes(i + 1, end);

            // 构造树
            for (TreeNode left : leftTree) {
                for (TreeNode right : rightTree) {
                    TreeNode node = new TreeNode(i);
                    node.left = left;
                    node.right = right;
                    result.add(node);
                }
            }
        }
        return result;
    }

    public int numTrees(int n) {
        // 处理边界
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                dp[i] += dp[j - 1] * dp[i - j];
            }
        }
        return dp[n];
    }

    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }

        if (root.left != null) {
            if (root.left.val > root.val) {
                return false;
            }
            isValidBST(root.left);
        }
        if (root.right != null) {
            if (root.right.val < root.val) {
                return false;
            }
            isValidBST(root.right);
        }
        return true;
    }


}
